#include<iostream>
#include<memory>
#include<string>
#include<list>
using namespace std;

class  Observer;
class Subject
{
public:
	virtual void Attach(Observer *pObserver) = 0;
	virtual void Detach(Observer *pObserver) = 0;
	virtual void Notify() = 0;
	virtual void SetData(string bookName) = 0;
	virtual string GetData() = 0;
	virtual ~Subject() {};
};

class Observer
{
public:
	virtual string GetName() = 0;
	virtual void Update(Subject* pSubject) = 0;
};

class Library : public Subject
{
public:
	Library()
	{
		m_pStudentList = new list<Observer*>();
	}
	~Library()
	{
		list<Observer*>::iterator ite = m_pStudentList->begin();
		while ( ite != m_pStudentList->end())
		{
			delete *ite;
			ite++;
		}
	}
	virtual void Attach(Observer * observer)
	{
		m_pStudentList->push_back(observer);
	}

	virtual void Detach(Observer *pObserver)
	{
		list<Observer*>::iterator ite = m_pStudentList->begin();
		while ( ite != m_pStudentList->end())
		{
			if ((*ite)->GetName() == pObserver->GetName())
			{
				delete *ite;
				m_pStudentList->remove(*ite);
				break;
			}
			ite++;
		}
	}
	virtual void Notify()
	{
		list<Observer*>::iterator ite = m_pStudentList->begin();
		while ( ite != m_pStudentList->end())
		{
			(*ite)->Update(this);
			ite++;
		}
	}

	virtual void SetData(string bookName)
	{
		this->bookName = bookName;
	}

	virtual string GetData()
	{
		return bookName;
	}

private:
	list<Observer*> *m_pStudentList;
	string bookName;
};



class Student : public Observer
{
public:
	Student(string name)
	{
		studentName = name;
	}
	virtual string GetName()
	{
		return studentName;
	}
	virtual void Update(Subject* pSubject)
	{
		cout<<GetName()<<"  "<<pSubject->GetData()+" is here"<<endl;
	}
private:
	string studentName;
};
int main3()
{
	auto_ptr<Subject> pSubject(new Library());
	pSubject->SetData("Design Pattern");

	Student *pS1 = new Student("John");
	Student *pS2 = new Student("Jim");
	Student *pS3 = new Student("Tom");
	Student *pS4 = new Student("Marry");
	pSubject->Attach(pS1);
	pSubject->Attach(pS2);
	pSubject->Attach(pS3);
	pSubject->Attach(pS4);
	pSubject->Notify();
	cout<<"**********************************"<<endl;
	pSubject->Detach(pS2);
	pSubject->Notify();
	
	cin.get();
	return 0;
}